home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / fpkpas92.zip / SRCRTL.ZIP / RTL / DOS / GO32.PP < prev    next >
Text File  |  1997-07-01  |  20KB  |  751 lines

  1. {****************************************************************************
  2.  
  3.                       Copyright (c) 1996 by Florian Klaempfl
  4.  
  5.  ****************************************************************************}
  6.  
  7. {
  8.   this unit is part of the FPKPascal run time library
  9.   and implements some stuff for protected mode programming
  10.  
  11.   History:
  12.        6th november 1996:
  13.          + dosmem* implemented
  14. }
  15.  
  16. unit go32;
  17.  
  18.   interface
  19.  
  20.     const
  21.        { contants for the run modes returned by get_run_mode }
  22.        rm_unknown = 0;
  23.        { raw (without HIMEM) }
  24.        rm_raw = 1;
  25.        { XMS (for example with HIMEM, without EMM386) }
  26.        rm_xms = 2;
  27.        { VCPI (for example HIMEM and EMM386) }
  28.        rm_vcpi = 3;
  29.        { DPMI (for example DOS box or 386Max) }
  30.        rm_dpmi = 4;
  31.   
  32.     type
  33.        tmeminfo = record
  34.           available_memory : longint;
  35.           available_pages : longint;
  36.           available_lockable_pages : longint;
  37.           linear_space : longint;
  38.           unlocked_pages : longint;
  39.           available_physical_pages : longint;
  40.           total_physical_pages : longint;
  41.           free_linear_space : longint;
  42.           max_pages_in_paging_file : longint;
  43.           reserved : array[0..2] of longint;
  44.        end;
  45.               
  46.        tseginfo = record
  47.           offset : pointer;
  48.           segment : word;
  49.        end;
  50.  
  51.        registers=record
  52.           case integer of
  53.            0 : (di,ff1,si,ff2,bp,ff3,ff4,ff5,bx,ff6,dx,ff7,cx,
  54.                 ff8,ax,ff9,flags,es,ds,fs,gs,ip,cs,sp,ss : word);
  55.            1 : (edi,esp,ebp,res : longint;
  56.                bl,bh,ff10,ff11,dl,dh,ff12,ff13,
  57.                cl,ch,ff14,ff15,al,ah : byte);
  58.            2 : (realedi,realesi,realebp,realres,
  59.                 realebx,realedx,realecx,realeax : longint;
  60.                 realflags,
  61.                 reales,realds,realfs,realgs,
  62.                 realip,realcs,realsp,realss : word);
  63.            3 : (bisedi,bisesi,bisebp,bisres,
  64.                 ebx,edx,ecx,eax : longint);
  65.            end;
  66.  
  67.        trealregs=registers;
  68.        {
  69.           realedi,realesi,realebp,realres,
  70.           realebx,realedx,realecx,realeax : longint;
  71.  
  72.           realflags,
  73.           reales,realds,realfs,realgs,
  74.           realip,realcs,realsp,realss : word;
  75.        end; }
  76.  
  77.     const carryflag = 1;
  78.       parityflag = 4;
  79.       auxcarryflag = $10;
  80.       zeroflag = $40;
  81.       signflag = $80;
  82.       trapflag = $100;
  83.       interruptflag = $200;
  84.       directionflag = $400;
  85.       overflowflag = $800;
  86.  
  87.     { this works only with real DPMI }
  88.     function allocate_ldt_descriptors(count : word) : word;
  89.     procedure free_ldt_descriptor(d : word);
  90.     function segment_to_descriptor(seg : word) : word;
  91.     function get_next_selector_increment_value : word;
  92.     function get_segment_base_address(d : word) : longint;
  93.     procedure set_segment_base_address(d : word;s : longint);
  94.     procedure set_segment_limit(d : word;s : longint);
  95.     function create_code_segment_alias_descriptor(seg : word) : word;
  96.     function get_linear_addr(phys_addr : longint;size : longint) : longint;
  97.     function get_segment_limit(d : word) : longint;
  98.     procedure realintr(intnr : word;var regs : trealregs);
  99.  
  100.     { is needed for functions which need a real mode buffer }
  101.     function  global_dos_alloc(bytes : longint) : longint;
  102.     procedure global_dos_free(selector : word);
  103.     
  104.     var
  105.        { selector for the DOS memory (only usable if in DPMI mode) }
  106.        dosmemselector : word;
  107.  
  108.     { this procedure copies data where the source and destination }
  109.     { are specified by 48 bit pointers                            }
  110.     { Note: the procedure checks only for overlapping if          }
  111.     { source selector=destination selector                        }
  112.     procedure seg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  113.  
  114.     { fills a memory area specified by a 48 bit pointer with c }
  115.     procedure seg_fillchar(seg : word;ofs : longint;count : longint;c : char);
  116.     procedure seg_fillword(seg : word;ofs : longint;count : longint;w : word);
  117.  
  118.     {************************************}
  119.     { this works with all PM interfaces: }
  120.     {************************************}
  121.  
  122.     procedure get_meminfo(var meminfo : tmeminfo);
  123.     procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);
  124.     procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);
  125.     function get_cs : word;
  126.     function get_ds : word;
  127.     function get_ss : word;
  128.  
  129.     { disables and enables interrupts }
  130.     procedure disable;
  131.     procedure enable;
  132.  
  133.     function inportb(port : word) : byte;
  134.     function inportw(port : word) : word;
  135.     function inportl(port : word) : longint;
  136.  
  137.     procedure outportb(port : word;data : byte);
  138.     procedure outportw(port : word;data : word);
  139.     procedure outportl(port : word;data : longint);
  140.     function get_run_mode : word;
  141.  
  142. {$ifdef GO32V2}
  143.     function transfer_buffer : longint;
  144.     function tb_size : longint;
  145.     procedure copytodos(var addr; len : longint);
  146.     procedure copyfromdos(var addr; len : longint);
  147. {$endif GO32V2}
  148.  
  149.    var
  150.        { this procedures are assigned to the procedure which are needed }
  151.        { for the current mode to access DOS memory                      }
  152.        { It's strongly recommended to use this procedures!              }
  153.        dosmemput : procedure(seg : word;ofs : word;var data;count : longint);
  154.        dosmemget : procedure(seg : word;ofs : word;var data;count : longint);
  155.        dosmemmove : procedure(sseg,sofs,dseg,dofs : word;count : longint);
  156.        dosmemfillchar : procedure(seg,ofs : word;count : longint;c : char);
  157.        dosmemfillword : procedure(seg,ofs : word;count : longint;w : word);
  158.  
  159.   implementation
  160.  
  161.     { the following procedures copy from and to DOS memory without DPMI }
  162.     procedure raw_dosmemput(seg : word;ofs : word;var data;count : longint);
  163.  
  164.       begin
  165.          move(data,pointer($e0000000+seg*16+ofs)^,count);
  166.       end;
  167.  
  168.     procedure raw_dosmemget(seg : word;ofs : word;var data;count : longint);
  169.  
  170.       begin
  171.          move(pointer($e0000000+seg*16+ofs)^,data,count);
  172.       end;
  173.  
  174.     procedure raw_dosmemmove(sseg,sofs,dseg,dofs : word;count : longint);
  175.  
  176.       begin
  177.          move(pointer($e0000000+sseg*16+sofs)^,pointer($e0000000+dseg*16+dofs)^,count);
  178.       end;
  179.       
  180.     procedure raw_dosmemfillchar(seg,ofs : word;count : longint;c : char);
  181.     
  182.       begin
  183.          fillchar(pointer($e0000000+seg*16+ofs)^,count,c);
  184.       end;
  185.       
  186.     procedure raw_dosmemfillword(seg,ofs : word;count : longint;w : word);
  187.     
  188.       begin
  189.          fillword(pointer($e0000000+seg*16+ofs)^,count,w);
  190.       end;
  191.       
  192.     { the following procedures copy from and to DOS memory using DPMI }
  193.     procedure dpmi_dosmemput(seg : word;ofs : word;var data;count : longint);
  194.  
  195.       begin
  196.          seg_move(get_ds,longint(@data),dosmemselector,seg*16+ofs,count);
  197.       end;
  198.  
  199.     procedure dpmi_dosmemget(seg : word;ofs : word;var data;count : longint);
  200.  
  201.       begin
  202.          seg_move(dosmemselector,seg*16+ofs,get_ds,longint(@data),count);
  203.       end;
  204.  
  205.     procedure dpmi_dosmemmove(sseg,sofs,dseg,dofs : word;count : longint);
  206.  
  207.       begin
  208.          seg_move(dosmemselector,sseg*16+sofs,dosmemselector,dseg*16+dofs,count);
  209.       end;
  210.  
  211.     procedure dpmi_dosmemfillchar(seg,ofs : word;count : longint;c : char);
  212.     
  213.       begin
  214.          seg_fillchar(dosmemselector,seg*16+ofs,count,c);
  215.       end;
  216.       
  217.     procedure dpmi_dosmemfillword(seg,ofs : word;count : longint;w : word);
  218.     
  219.       begin
  220.          seg_fillword(dosmemselector,seg*16+ofs,count,w);
  221.       end;
  222.       
  223.     function global_dos_alloc(bytes : longint) : longint;
  224.  
  225.       begin
  226.          asm
  227.             movl bytes,%ebx
  228.             orl  $0x10,%ebx             // round up
  229.             shrl $0x4,%ebx              // convert to Paragraphs
  230.             movw $0x100,%ax             // function 0x100
  231.             int  $0x31
  232.             shll $0x10,%eax             // return Segment in hi(Result)
  233.             movw %dx,%ax                // return Selector in lo(Result)
  234.             movl %eax,__result
  235.          end;
  236.       end;
  237.  
  238.     procedure  global_dos_free(selector : word);
  239.  
  240.       begin
  241.          asm
  242.             movw Selector,%dx
  243.             movw $0x101,%ax
  244.             int  $0x31
  245.          end;
  246.       end;
  247.  
  248.     procedure realintr(intnr : word;var regs : trealregs);
  249.  
  250.       begin
  251.      regs.realsp:=0;
  252.      regs.realss:=0;
  253.          asm
  254.             movw  intnr,%bx
  255.             xorl  %ecx,%ecx
  256.             movl  regs,%edi
  257.  
  258.             // es is always equal ds
  259.             movw  $0x300,%ax
  260.             int   $0x31
  261.          end;
  262.       end;
  263.  
  264.     procedure seg_fillchar(seg : word;ofs : longint;count : longint;c : char);
  265.  
  266.       begin
  267.          asm
  268.             movl ofs,%edi
  269.             movl count,%ecx
  270.             movb c,%dl
  271.             { load es with selector }
  272.             pushw %es
  273.             movw seg,%ax
  274.             movw %ax,%es
  275.             { fill eax with duplicated c }
  276.             { so we can use stosl        }
  277.             movb %dl,%dh
  278.             movw %dx,%ax
  279.             shll $16,%eax
  280.             movw %dx,%ax
  281.             movl %ecx,%edx
  282.             shrl $2,%ecx
  283.             cld
  284.             rep
  285.             stosl
  286.             movl %edx,%ecx
  287.             andl $3,%ecx
  288.             rep
  289.             stosb
  290.             popw %es
  291.          end ['EAX','ECX','EDX','EDI'];
  292.       end;
  293.  
  294.     procedure seg_fillword(seg : word;ofs : longint;count : longint;w : word);
  295.  
  296.       begin
  297.          asm
  298.             movl ofs,%edi
  299.             movl count,%ecx
  300.             movw w,%dx
  301.             { load segment }
  302.             pushw %es
  303.             movw seg,%ax
  304.             movw %ax,%es
  305.             { fill eax }
  306.             movw %dx,%ax
  307.             shll $16,%eax
  308.             movw %dx,%ax
  309.             movl %ecx,%edx
  310.             shrl $1,%ecx
  311.             cld
  312.             rep
  313.             stosl
  314.             movl %edx,%ecx
  315.             andl $1,%ecx
  316.             rep
  317.             stosw
  318.             popw %es
  319.          end ['EAX','ECX','EDX','EDI'];
  320.       end;
  321.  
  322.     procedure seg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  323.  
  324.       begin
  325.          if count=0 then
  326.            exit;
  327.          if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  328.            asm
  329.               pushw %es
  330.               pushw %ds
  331.               cld
  332.               movl count,%ecx
  333.               movl source,%esi
  334.               movl dest,%edi
  335.               movw dseg,%ax
  336.               movw %ax,%es
  337.               movw sseg,%ax
  338.               movw %ax,%ds
  339.               movl %ecx,%eax
  340.               shrl $2,%ecx
  341.               rep
  342.               movsl
  343.               movl %eax,%ecx
  344.               andl $3,%ecx
  345.               rep
  346.               movsb
  347.               popw %ds
  348.               popw %es
  349.            end ['ESI','EDI','ECX','EAX']
  350.          else if (source<dest) then
  351.            { copy backward for overlapping }
  352.            asm
  353.               pushw %es
  354.               pushw %ds
  355.               std              
  356.               movl count,%ecx
  357.               movl source,%esi
  358.               movl dest,%edi
  359.               movw dseg,%ax
  360.               movw %ax,%es
  361.               movw sseg,%ax
  362.               movw %ax,%ds
  363.               addl %ecx,%esi
  364.               addl %ecx,%edi
  365.               movl %ecx,%eax
  366.               andl $3,%ecx
  367.               orl %ecx,%ecx
  368.               jz LSEG_MOVE1
  369.               
  370.               { calculate esi and edi}
  371.               decl %esi
  372.               decl %edi
  373.               rep
  374.               movsb
  375.               incl %esi
  376.               incl %edi
  377.            LSEG_MOVE1:
  378.               subl $4,%esi
  379.               subl $4,%edi
  380.               movl %eax,%ecx
  381.               shrl $2,%ecx
  382.               rep
  383.               movsl
  384.               cld
  385.               popw %ds
  386.               popw %es
  387.            end ['ESI','EDI','ECX'];
  388.       end;
  389.  
  390.     procedure outportb(port : word;data : byte);
  391.  
  392.       begin
  393.          asm
  394.             movw port,%dx
  395.             movb data,%al
  396.             outb %al,%dx
  397.          end ['EAX','EDX'];
  398.       end;
  399.  
  400.     procedure outportw(port : word;data : word);
  401.  
  402.       begin
  403.          asm
  404.             movw port,%dx
  405.             movw data,%ax
  406.             outw %ax,%dx
  407.          end ['EAX','EDX'];
  408.       end;
  409.  
  410.     procedure outportl(port : word;data : longint);
  411.  
  412.       begin
  413.          asm
  414.             movw port,%dx
  415.             movl data,%eax
  416.             outl %eax,%dx
  417.          end ['EAX','EDX'];
  418.       end;
  419.  
  420.     function inportb(port : word) : byte;
  421.  
  422.       begin
  423.          asm
  424.             movw port,%dx
  425.             inb %dx,%al
  426.             movb %al,__RESULT
  427.          end ['EAX','EDX'];
  428.       end;
  429.  
  430.     function inportw(port : word) : word;
  431.  
  432.       begin
  433.          asm
  434.             movw port,%dx
  435.             inw %dx,%ax
  436.             movw %ax,__RESULT
  437.          end ['EAX','EDX'];
  438.       end;
  439.  
  440.     function inportl(port : word) : longint;
  441.  
  442.       begin
  443.          asm
  444.             movw port,%dx
  445.             inl %dx,%eax
  446.             movl %eax,__RESULT
  447.          end ['EAX','EDX'];
  448.       end;
  449.  
  450.     function get_cs : word;
  451.     
  452.       begin
  453.          asm
  454.             movw %cs,%ax
  455.             movw %ax,__RESULT;
  456.          end;
  457.       end; 
  458.  
  459.    
  460.     function get_ss : word;
  461.     
  462.       begin
  463.          asm
  464.             movw %ss,%ax
  465.             movw %ax,__RESULT;
  466.          end;
  467.       end; 
  468.    
  469.     function get_ds : word;
  470.  
  471.       begin
  472.          asm
  473.             movw %ds,%ax
  474.             movw %ax,__RESULT;
  475.          end;
  476.       end; 
  477.    
  478.     procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);
  479.     
  480.       begin
  481.          asm
  482.             movl intaddr,%eax
  483.             movl (%eax),%edx
  484.             movw 4(%eax),%cx
  485.             movw $0x205,%ax
  486.             movb vector,%bl
  487.             int $0x31
  488.          end;
  489.       end;
  490.  
  491.     procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);
  492.     
  493.       begin
  494.          asm
  495.             movb vector,%bl
  496.             movw $0x204,%ax        
  497.             int $0x31
  498.             movl intaddr,%eax
  499.             movl %edx,(%eax)
  500.             movw %cx,4(%eax)
  501.          end;
  502.       end;
  503.       
  504.     function allocate_ldt_descriptors(count : word) : word;
  505.     
  506.       begin
  507.          asm
  508.             movw count,%cx
  509.             movw $0,%ax
  510.             int $0x31
  511.             movw %ax,__RESULT
  512.          end;
  513.       end;
  514.     
  515.     procedure free_ldt_descriptor(d : word);
  516.     
  517.       begin
  518.          asm
  519.              movw d,%bx
  520.              movw $1,%ax
  521.              int $0x31
  522.       end;
  523.        end;
  524.  
  525.     function segment_to_descriptor(seg : word) : word;
  526.     
  527.       begin
  528.          asm
  529.              movw seg,%bx
  530.              movw $2,%ax
  531.              int $0x31
  532.              movw %ax,__RESULT
  533.       end;
  534.        end;
  535.     
  536.     function get_next_selector_increment_value : word;
  537.     
  538.       begin
  539.          asm
  540.              movw $3,%ax
  541.              int $0x31
  542.              movw %ax,__RESULT
  543.       end;
  544.        end;
  545.  
  546.     function get_segment_base_address(d : word) : longint;
  547.  
  548.       begin
  549.          asm
  550.             movw d,%bx
  551.             movw $6,%ax
  552.             int $0x31
  553.             xorl %eax,%eax
  554.             movw %dx,%ax
  555.             shll $16,%ecx
  556.             orl %ecx,%eax
  557.             movl %eax,__RESULT
  558.          end;
  559.       end;
  560.  
  561.     procedure set_segment_base_address(d : word;s : longint);
  562.  
  563.       begin
  564.          asm
  565.             movw d,%bx
  566.             leal s,%eax
  567.             movw (%eax),%dx
  568.             movw 2(%eax),%cx
  569.             movw $7,%ax
  570.             int $0x31
  571.          end;
  572.       end;
  573.  
  574.     procedure set_segment_limit(d : word;s : longint);
  575.  
  576.       begin
  577.          asm
  578.             movw d,%bx
  579.             leal s,%eax
  580.             movw (%eax),%dx
  581.             movw 2(%eax),%cx
  582.             movw $8,%ax
  583.             int $0x31
  584.          end;
  585.       end;
  586.  
  587.    function get_segment_limit(d : word) : longint;
  588.  
  589.       begin
  590.          asm
  591.             movzwl d,%eax
  592.             lsl %eax,%eax
  593.             jz L_ok
  594.             xorl %eax,%eax
  595.          L_ok:
  596.             movl %eax,__RESULT
  597.          end;
  598.       end;
  599.     function create_code_segment_alias_descriptor(seg : word) : word;
  600.     
  601.       begin
  602.          asm
  603.              movw seg,%bx
  604.              movw $0xa,%ax
  605.              int $0x31
  606.              movw %ax,__RESULT
  607.       end;
  608.        end;
  609.        
  610.     procedure get_meminfo(var meminfo : tmeminfo);
  611.     
  612.       begin
  613.          asm
  614.             movl meminfo,%edi
  615.             movw $0x500,%ax
  616.             int $0x31
  617.          end;
  618.       end;   
  619.       
  620.     function get_linear_addr(phys_addr : longint;size : longint) : longint;
  621.     
  622.       begin
  623.          asm
  624.             movl phys_addr,%ebx
  625.             movl %ebx,%ecx
  626.             shrl $16,%ebx
  627.             movl phys_addr,%esi
  628.             movl %esi,%edi
  629.             shrl $16,%esi
  630.             movw $0x800,%ax
  631.             int $0x31
  632.             shll $16,%ebx
  633.             movw %cx,%bx
  634.             movl %ebx,__RESULT
  635.          end;
  636.       end;
  637.  
  638.     procedure disable;
  639.  
  640.       begin
  641.          asm
  642.             cli;
  643.          end;
  644.       end;
  645.  
  646.     procedure enable;
  647.  
  648.       begin
  649.          asm
  650.             sti;
  651.          end;
  652.       end;
  653.  
  654.     function get_run_mode : word;
  655.  
  656.       begin
  657.          asm
  658.             movw _run_mode,%ax
  659.             movw %ax,__RESULT
  660.          end ['EAX'];
  661.       end;
  662. {
  663. typedef struct {
  664.   unsigned long handle;            /* 0, 2 */
  665.   unsigned long size;     /* or count */    /* 4, 6 */
  666.   unsigned long address;        /* 8, 10 */
  667. } __dpmi_meminfo;
  668.     procedure map_device_in_memory_block(const meminfo : tmeminfo;
  669.       phys_addr : longint);
  670.  
  671.       begin
  672.          asm
  673.         movl meminfo,%eax
  674.             movl (%eax),%esi
  675.         movl 4(%eax),%ecx
  676.         movl 8(%eax),%ebx
  677.         movl phys_addr,%edx
  678.             movw $0x508,%ax
  679.             int $0x31
  680.          end;
  681.       end;
  682. }
  683.  
  684.     function get_core_selector : word;
  685.     
  686.       begin
  687.          asm
  688.             movw _core_selector,%ax
  689.             movw %ax,__RESULT
  690.          end;
  691.       end;
  692.  
  693. {$ifdef GO32V2}
  694.  
  695.     function transfer_buffer : longint;
  696.     begin
  697.     transfer_buffer := go32_info_block.linear_address_of_transfer_buffer;
  698. {       asm
  699.        leal __go32_info_block,%ebx
  700.        movl 12(%ebx),%eax
  701.        leave
  702.        ret
  703.        end ['EAX','EBX'];}
  704.     end;
  705.  
  706.     function tb_size : longint;
  707.     begin
  708.     tb_size := go32_info_block.size_of_transfer_buffer;
  709. {       asm
  710.        leal __go32_info_block,%ebx
  711.        movl 16(%ebx),%eax
  712.        leave
  713.        ret
  714.        end ['EAX','EBX'];}
  715.     end;
  716.  
  717.      procedure copytodos(var addr; len : longint);
  718.      begin
  719.         if len > tb_size then runerror(200);
  720.         seg_move(get_ds,longint(@addr),dosmemselector,transfer_buffer,len);
  721.      end;
  722.  
  723.      procedure copyfromdos(var addr; len : longint);
  724.      begin
  725.         if len > tb_size then runerror(200);
  726.         seg_move(dosmemselector,transfer_buffer,get_ds,longint(@addr),len);
  727.      end;
  728.  
  729. {$endif GO32V2}
  730.  
  731. begin
  732.    if get_run_mode=rm_dpmi then
  733.      begin
  734.         dosmemget:=@dpmi_dosmemget;
  735.         dosmemput:=@dpmi_dosmemput;
  736.         dosmemmove:=@dpmi_dosmemmove;
  737.         dosmemfillchar:=@dpmi_dosmemfillchar;
  738.         dosmemfillword:=@dpmi_dosmemfillword;
  739.         dosmemselector:=get_core_selector;
  740.      end
  741.    else
  742.      begin
  743.         dosmemget:=@raw_dosmemget;
  744.         dosmemput:=@raw_dosmemput;
  745.         dosmemmove:=@raw_dosmemmove;
  746.         dosmemfillchar:=@raw_dosmemfillchar;
  747.         dosmemfillword:=@raw_dosmemfillword;
  748.      end;
  749. end.
  750.  
  751.